// Copyright (C) 1997, All Rights Reserved, by
// EMC Corporation, Hopkinton MA.
//
// This software is furnished under a license and may be used and copied
// only  in  accordance  with  the  terms  of such  license and with the
// inclusion of the above copyright notice. This software or  any  other
// copies thereof may not be provided or otherwise made available to any
// other person. No title to and ownership of  the  software  is  hereby
// transferred.
//
// The information in this software is subject to change without  notice
// and  should  not be  construed  as  a commitment by EMC Corporation.
//
// EMC assumes no responsibility for the use or  reliability  of its
// software on equipment which is not supplied by EMC.

#if !defined(_LOGMEM_BUFFER_HXX_)
#define _LOGMEM_BUFFER_HXX_

#if !defined(lint) && defined(INCLUDE_RCSID)
/* static char logmem_buffer_hxx_rcsid[] =
"$Id: logmem_buffer.hxx,v 11.3 2010/02/20 00:53:37 williw Exp $"
"$Source: /usr/local/cvs/archive/Dart/server/src/kernel/min_kernel/include/logmem_buffer.hxx,v $"; */
#endif
 

// FACILITY:
// 
// Memory buffer (cyclic or non-cyclic)
//
// ABSTRACT:
//
//  Auxiliary class which allows accumulation of character data up to
//  pre-defined capacity. If there are requests that exceed this capacity,
//  then data is either truncated or wrapped around, depending on the 
//  flag given in the constructor.
// 
//
// AUTHORS:
//
// Boris Farizon
//
// CREATION DATE:
// 
// Aug 28, 1997
//
// MODIFICATION HISTORY:
//

// Log information available via 'cvs log'
 

#include <boolean.h>

// Template definition of Min(), Max() operations;
// should probably be placed to become commonly available
#ifndef Min
#define Min(a,b) ((a) < (b) ? (a) : (b))
// when the compiler allows us, we'll use the template
#if 0
template <class Type>
Type Min( Type a, Type b )
{
  return (a < b) ? (a : b);
}
#endif // 0
#endif
#ifndef Max
#define Max(a,b) ((a) > (b) ? (a) : (b))
// when the compiler allows us, we'll use the template
#if 0
template <class Type>
Type Max( Type a, Type b )
{
  return (a > b) ? (a : b);
}
#endif // 0
#endif

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//  Definition of the class cMemoryBuffer.
//  Auxiliary class which allows accumulation of character data up to
//  pre-defined capacity. If there are requests that exceed this capacity,
//  then data is either truncated or wrapped around, depending on the 
//  flag given in the constructor
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
class cMemoryBuffer {
public:
  cMemoryBuffer(boolean_t boolTruncate = TRUE, int buffSize = 0, 
                char* extrnBuffer = (char *) 0);
  // Constructor (default)
  // if boolTruncate is TRUE, then no more than buffer size
  // bytes can and will be written; otherwise, extra bytes are 'wrapped around'
  // External char buffer can be provided to store data in it instead
  // of allocating memory internally (extrnBuffer != NULL && buffSize > 0).
  // If the specified size is <=0, use the default size (and don't use
  // external buffer even if it's provided.

  cMemoryBuffer(const cMemoryBuffer& rMemBuf);
  // Copy constructor
    
  ~cMemoryBuffer();
  // Destructor
 
  cMemoryBuffer& operator=( const cMemoryBuffer& rMemBuf );
  // overloaded assignment operator
 
  // Public access and manipulation functions
  //

  int putStr(char * srcBuff, int charCount);
  // Write array of bytes to the buffer
 
  int putChar(char ch);
  // Write a single char to the buffer

  int getLeastRecentChunk(char* destBuf, int charCount = 0) const;
  // Copies charCount least recent bytes to the provided buffer
  // (starting from the least recently written). 
  // if charCount == 0, the entire contents of the buffer is copied

  int getMostRecentChunk(char* destBuf, int charCount = 0) const;
  // Copies charCount most recent bytes to the provided buffer
  // (starting from the least recently written). 
  // if charCount == 0, the entire contents of the buffer is copied

  int getSize(void) const;
  // Get buffer size

  int getCharCount(void) const;
  // Get current number of chars in the buffer

  boolean_t isFull(void) const;
  // returns TRUE if the buffer is full; otherwise, returns FALSE

  void empty(void);
  // reset the buffer (empty it)
  
  boolean_t isTruncated(void) const;
  // returns TRUE if the data was actually truncated

  void initByExample(const cMemoryBuffer& rMemBuff);
  // initializes *this* object by the state of the supplied one
  // does nothing if the supplied object is in invalid state
   
  void chgBufCounterIndex(int cnt); 
  // Changes index values for m_FreeIndex and  m_CharCount 
  // if the arguments of message is long enough to be printed 
  // also resets the truncation flag m_Truncated. 

protected:
  enum { MemBuff_DefaultSize = 512 };
  // default buffer size (if 0 is specified in constructor call)

  enum { MemBuff_WriteFail, MemBuff_WriteOk };
  // write status (internal)

  typedef enum { MemBuff_Client, MemBuff_thisObject } MemoryProvider;
  // buffer memory allocator -- this object
  // or client (provided by the user)

  int doWriteChar(char ch);
  // actually write char

  boolean_t shouldTruncate(void) const;
  // returns TRUE if any extra data is truncated, FALSE if it's wrapped around

  int copySubbuffer(char* destBuff, int startIndex, int numBytesToCopy) const;
  // utility used to avoid code duplications; copies numBytesToCopy bytes
  // from the buffer to destination. Wraps around if necessary.

  boolean_t isLocalMemory(void) const;
  // returns TRUE if memory for the buffer was allocated by object's ctor;
  // returns FALSE if the object uses client-provided memory

  boolean_t isClientMemory(void) const;
  // the reverse of isLocalMemory()

protected:
  char*          m_Buffer;               // pointer to the actual buffer in memory
  int            m_BuffSize;             // size of the buffer
  int            m_CharCount;            // number of chars in the buffer
  int            m_FreeIndex;            // index of the 'free' slot
  int            m_LeastRecentIndex;     // index of the least recently written char
  boolean_t      m_ShouldTruncate;       // truncate / wrap around flag
  boolean_t      m_Truncated;            // TRUE if data was actually truncated
  MemoryProvider m_MemProvider;          // buffer memory provider -- this object
                                         // or client 
};   

 
//////////////////////////////////////////////////////////////////////////////
////  INLINES
//////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////
//// int cMemoryBuffer::putChar(char ch)
////
//// DESCRIPTION
//// Writes a single character to the buffer.
//// RETURNS 
//// 1 if success,0 otherwise
//////////////////////////////////////////////////////////////////////////////
inline int cMemoryBuffer::putChar(char ch)
{
  return ((doWriteChar(ch) == MemBuff_WriteOk) ? 1 : 0);
}

// inline boolean_t cMemoryBuffer::isFull(void) 
//
inline boolean_t cMemoryBuffer::isFull(void) const
{
  return (m_CharCount >= m_BuffSize);
}

// inline boolean_t cMemoryBuffer::shouldTruncate(void)
//
inline boolean_t cMemoryBuffer::shouldTruncate(void) const
{
  return (m_ShouldTruncate);
}

// inline int cMemoryBuffer::getSize(void)
//
inline int cMemoryBuffer::getSize(void) const
{
  return m_BuffSize;
}

// inline int cMemoryBuffer::getCharCount(void)
//
inline int cMemoryBuffer::getCharCount(void) const
{
  return m_CharCount;
}
// inline void cMemoryBuffer::empty(void)
//
inline void cMemoryBuffer::empty(void)
{
  m_LeastRecentIndex = 0;
  m_FreeIndex = 0;
  m_CharCount = 0; 
  m_Truncated = (boolean_t) FALSE;
}

// inline boolean_t cMemoryBuffer::isTruncated(void)
//
inline boolean_t cMemoryBuffer::isTruncated(void) const
{
  return m_Truncated;
}

// inline int cMemoryBuffer::copySubbuffer(char* destBuff, int startIndex, int numBytesToCopy)
//
// Utility used to avoid code duplications; copies numBytesToCopy bytes
// from the buffer to destination. Wraps around if necessary.

inline int cMemoryBuffer::copySubbuffer(char* destBuff, int startIndex, int numBytesToCopy) const
{
  for (int i = 0; i < numBytesToCopy; i++)
  {
    destBuff[i] = m_Buffer[ (startIndex + i) % m_BuffSize ];
  }
  return numBytesToCopy;
}

// inline void cMemoryBuffer::chgBufCounterIndex(int cnt) 
// 
// Changes the index values for m_FreeIndex, m_CharCount and m_LeastRecentIndex 
// if argument of a message is to be skipped. 
// truncation flag is also reset. 
inline void cMemoryBuffer::chgBufCounterIndex(int cnt) 
{ 
 m_CharCount = cnt; 
 m_FreeIndex = cnt; 
 m_Truncated = 0; 
} 

// inline boolean_t cMemoryBuffer::isLocalMemory(void)
//
// Returns TRUE if memory for the buffer was allocated by object's ctor;
// returns FALSE if the object uses client-supplied memory
inline boolean_t cMemoryBuffer::isLocalMemory(void) const
{
  return (m_MemProvider == MemBuff_thisObject);
}

// inline boolean_t cMemoryBuffer::isClientMemory(void)
//
// the reverse of isLocalMemory()
inline boolean_t cMemoryBuffer::isClientMemory(void) const
{
  return (m_MemProvider == MemBuff_Client);
}

#endif // _LOGMEM_BUFFER_HXX_
